package com.woniuxy.springbootrabbit.configuration;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class RabbitConfiguration {
    /**
     * simple  work
     */
    @Bean
    public Queue simpleQueue(){
        return new Queue("simple_queue");
    }

    /**
     * 发布订阅模式
     * 1.创建两个消息队列
     * 2.创建一个交换机  fanout
     * 3.需要将消息队列绑定到交换上
     */

    @Bean // 默认情况下会将方法名作为bean的名字
    public Queue publishA(){
        return new Queue("publish_a");
    }
    @Bean
    public Queue publishB(){
        return new Queue("publish_b");
    }

    @Bean
    public FanoutExchange publishExchange(){
        return new FanoutExchange("publish_exchange");
    }

    // 绑定消息队列到交换机上
    // 在调用该方法创建对象时，IOC容器会根据参数的名字自动注入对应的bean对象
    @Bean
    public Binding bindingPublishAToPublishExchange(Queue publishA,FanoutExchange publishExchange){
        // 将消息队列绑定到交换机
        return BindingBuilder.bind(publishA).to(publishExchange);
    }

    @Bean
    public Binding bindingPublishBToPublishExchange(Queue publishB,FanoutExchange publishExchange){
        // 将消息队列绑定到交换机
        return BindingBuilder.bind(publishB).to(publishExchange);
    }

    /**
     * 路由模式
     */
    @Bean
    public Queue directQueueA(){
        return new Queue("direct_a");
    }
    @Bean
    public Queue directQueueB(){
        return new Queue("direct_b");
    }
    @Bean
    public DirectExchange directExchange(){
        return new DirectExchange("direct_exchange");
    }
    @Bean
    public Binding bindingDirectQueueAToDirectExchange(Queue directQueueA,DirectExchange directExchange){
        return BindingBuilder.bind(directQueueA).to(directExchange).with("red");
    }
    @Bean
    public Binding bindingDirectQueueBToDirectExchange(Queue directQueueB,DirectExchange directExchange){
        return BindingBuilder.bind(directQueueB).to(directExchange).with("green");
    }

    /**
     * 主题模式
     */
    @Bean
    public Queue topicA(){
        return new Queue("topic_a");
    }
    @Bean
    public Queue topicB(){
        return new Queue("topic_b");
    }
    @Bean
    public TopicExchange topicExchange(){
        return new TopicExchange("topic_exchange");
    }
    @Bean
    public Binding bindingTopicAToTopicExchange(Queue topicA, TopicExchange topicExchange){
        return BindingBuilder.bind(topicA).to(topicExchange).with("chengdu.#");
    }
    @Bean
    public Binding bindingTopicBToTopicExchange(Queue topicB, TopicExchange topicExchange){
        return BindingBuilder.bind(topicB).to(topicExchange).with("#.news");
    }

    /**
     * 延迟队列
     */
    //正常的业务队列、交换机
    @Bean
    public Queue ttlQueue(){
        // 创建消息队列时指定参数：过期时间、死信交换机、死信路由等信息
        Map<String,Object> map = new HashMap<>();

        // 给当前消息队列指定死信交换：才能将过期的消息转发给死信交换机
        map.put("x-dead-letter-exchange","dead_exchange");   // 参数2：死信交换机的名字

        // 指定死信路由：当消息过期时转发给死信交换机时用到的路由，死信交换机根据该路由信息将消息转发给指定的消息队列
        map.put("x-dead-letter-routing-key","dead");  //参数2：路由名

        // 指定当前消息队列上所有消息的过期时间，所有消息的过期时间都是一样的   单位是毫秒
        map.put("x-message-ttl",5000);

        // 设置参数
        // 参数1：消息队列的名字
        // 参数2：是否持久化消息
        // 参数3：是否排它
        // 参数4：是否自动删除消息队列
        // 参数5：创建消息队列时的参数，例如死信交换机、路由、过期时间、队列长度
        return new Queue("ttl_queue",true,false,false,map);
    }
    @Bean
    public DirectExchange ttlExchange(){
        return new DirectExchange("ttl_exchange");
    }
    @Bean
    public Binding bindingTtlQueueToTtlExchange(Queue ttlQueue, DirectExchange ttlExchange){
        return BindingBuilder.bind(ttlQueue).to(ttlExchange).with("ttl");
    }
    // 死信交换机、死信队列：死信交换机、队列其实就是普通的交换机和消息队列，只是它们是用来专门接收死信的，所有称之为死信交换机、消息队列
    @Bean
    public Queue deadQueue(){
        return new Queue("dead_queue");
    }
    @Bean
    public DirectExchange deadExchange(){
        return new DirectExchange("dead_exchange");
    }
    @Bean
    public Binding bindingDeadQueueToDeadExchange(Queue deadQueue, DirectExchange deadExchange){
        return BindingBuilder.bind(deadQueue).to(deadExchange).with("dead");
    }


    /**
     * 延迟插件
     */
    @Bean
    public Queue delayQueue(){
        return new Queue("delay_queue");
    }

    @Bean  // 自定义的交换机
    public CustomExchange customExchange(){
        Map<String,Object> map = new HashMap<>();

        // 指定交换机的类型：自定义的交换机基于哪一种交换机实现
        map.put("x-delayed-type","direct");

        // 创建交换看
        // 参数1：交换机的名字
        // 参数2：交换机中消息的类型：延迟消息  都有自己的TTL时间
        // 参数3：是否持久化消息
        // 参数4：是否自动删除
        // 参数5：创建交换机的参数
        return new CustomExchange("delay_exchange","x-delayed-message",true,false,map);
    }

    @Bean
    public Binding bindingDelayQueueToCustomExchange(Queue delayQueue, CustomExchange customExchange){
        // to方法是一个重载方法
        return BindingBuilder.bind(delayQueue).to(customExchange).with("delay").noargs();
    }

}
